package service

import (
	"fmt"
	"sync"
)

var secLimitMgr = &SecLimitMgr{
	UserLimitMap: make(map[int]*SecLimit, 10000),
	IpLimitMap:   make(map[string]*SecLimit, 10000),
}

type SecLimitMgr struct {
	UserLimitMap map[int]*SecLimit
	IpLimitMap   map[string]*SecLimit
	lock         sync.Mutex
}

func AntiSpam(req *SecRequest) (err error) {
	secLimitMgr.lock.Lock()
	secLimit, ok := secLimitMgr.UserLimitMap[req.UserId]
	if !ok {
		secLimit = &SecLimit{}
		secLimitMgr.UserLimitMap[req.UserId] = secLimit
	}
	count := secLimit.Count(req.AccessTime.Unix())
	if count > secKillConf.UserSecAccessLimit {
		err = fmt.Errorf("invalid request")
		return
	}
	ipLimit, ok := secLimitMgr.IpLimitMap[req.ClientAddr]
	if !ok {
		ipLimit = &SecLimit{}
		secLimitMgr.IpLimitMap[req.ClientAddr] = ipLimit
	}
	count = ipLimit.Count(req.AccessTime.Unix())
	defer secLimitMgr.lock.Unlock()
	if count > secKillConf.IPSecAccessLimit {
		err = fmt.Errorf("invalid request")
		return
	}

	return
}

type SecLimit struct {
	count   int
	curTime int64
}

func (s *SecLimit) Count(nowTime int64) (curCount int) {
	if s.curTime != nowTime {
		s.count = 1
		s.curTime = nowTime
		curCount = s.count
		return
	}
	s.count++
	curCount = s.count
	return
}
